#pragma once
#include <vector>
#include "global_config.h"
#include <assert.h>
#include "position.h"
#include "MessageRouter.h"

struct GameInput;
struct V2;
struct Inventory;
struct Entity;

typedef Uint64 ENT_ID_int;

//used in factories
enum EntityType{
	ENTITY_TYPE_UNKNOWN = 0,
	ENTITY_TYPE_PLAYER,
	ENTITY_TYPE_WOODCHIPPER,
	ENTITY_TYPE_ITEM,
	ENTITY_TYPE_PROJECTILE
};

struct Entity
{
	//ObserverCollection * _observers;
	GameInput * input;
	ENT_ID_int id;
	EntityType _type;
	V2 size;
	Inventory * inventory;
	Inventory * other;

	//link this to a image description
	Uint16 sprite_index;	//facing left
	Uint64 flags;

	//if entity is item facade
	ITEM_TypeId_int item_type;
	ITEM_Amount_int item_amount;

	//these are hidden
	Position _pos_;
	V2 _velocity_;
	V2 _acc_;

	bool operator == (const Entity & other)
	{
		return other.id == id;
	}

	Entity()
	{
		input = 0;
		id = 0;
		size = v2(0,0);
		inventory = 0;
		other = 0;
		sprite_index = 0;
		flags = 0;
		item_type = 0;
		item_amount = 0;
		_pos_.chunk_index = v2(0,0);
		_pos_.relative = v2(0,0);
		_pos_.world = v2(0,0);
		_velocity_= v2(0,0);
		_acc_ = v2(0,0);
		_type = ENTITY_TYPE_UNKNOWN;
		//_observers = 0;
	}

};

Position * entity_get_position(Entity * e);



enum EntityFlag{
	ENTITY_INACTIVE = 0,
	ENTITY_PLAYER= 1<<0,
	ENTITY_ENTITY_COLLISION= 1<<1,
	ENTITY_TILE_COLLISION = 1<<2,
	ENTITY_RIGHT_CLICKABLE = 1<<3,
	ENTITY_TAKES_ITEM = 1<<4,
	ENTITY_GIVES_ITEM = 1<<5,
	ENTITY_IS_ITEM  = 1<<6,
	ENTITY_HAS_GRAVITY = 1<<7,
	ENTITY_DESTROYED = 1<<8
};

GLOBAL_CONSTANT int ENTITY_FLAG_COUNT = (8);

int IsSet(const Entity * e, Uint32 flags);

struct Game;
struct Chunk;

//CLEANUP up to here!!

void entity_set_vel(Entity * e, V2 vel);
void entity_add_vel(float dt, Entity * e, V2 vel);

void entity_set_acc(Entity * e, V2 acc);
void entity_add_acc(float dt, Entity * e, V2 acc);

//re-canonicalizes position if entity has moved off current chunk
void entity_set_rel_pos(Chunk * chunk_array[G::CHUNK_COUNT][G::CHUNK_COUNT], Entity * e, V2 pos);
void entity_add_pos(Chunk * chunk_array[G::CHUNK_COUNT][G::CHUNK_COUNT], float dt, Entity * e, V2 pos);

//V2 entity_get_abs_pos(const Entity * e);
struct Chunk;

Entity * game_create_entity(Chunk * chunk_array[G::CHUNK_COUNT][G::CHUNK_COUNT], Chunk * chunk, EntityType et, V2 _pos, int item_amount, int item_type);

//returns false when entity is destroyed
bool entity_update(float ft, Chunk * chunk_array[G::CHUNK_COUNT][G::CHUNK_COUNT], V2 camera_pos ,Chunk * chunk, Entity * entity);

void entity_destroy(Entity * e);
static MessageData entity_animation_listener(void * sender, std::string message, MessageData md)	
{
	MessageData Result;
	Entity * e = (Entity*)sender;

#if 0
	bool going_left = md.ints2[0] > md.ints2[2];
	if (going_left)
	{
		//e->sprite_index = 0;
	}
	else if (md.ints2[0] < md.ints2[2])
	{
		//e->sprite_index = 4;
	}
#endif

	return Result;
}